use Irssi 20020300;
use 5.6.0;
use strict;
use Socket;
use POSIX;

use vars qw($VERSION %IRSSI %HELP);
$HELP{gline} = "
GLINE [nicks|masks] ...

Glines the specified nicks or userhost masks.

If nick is given as parameter, a userhost of the type *!username\@*.host.domain.com will be used for the gline.
";
$VERSION = "1.0";
%IRSSI = (
  authors         => "Remco Brink",
  contact         => "remco\@rc6.org",
  name            => "gline",
  description     => "/BAN [nick|mask] - bans several nicks/masks on channel, removes any conflicting bans before banning",
  license         => "GNU GPLv2 or later",
  changed         => "Tue Aug 07 14:00:00 CET 2011"
);

# Changelog:
# 1.0
# - Initial release

my (%ftag, $parent, %modes, %modes_args, %b, @userhosts);

sub cmd_gline {
    my ($args, $server, $winit) = @_;

    my $tag = $server->{tag};

  Irssi::signal_stop();

  $b{$tag} = 0;

  # Count the amount of nicks/masks we'll be using
  for my $cmd (split(/ +/, $args)) {
    next unless $cmd;    
    $b{$tag}++;
  }
               
  # Loop through each record for the gline
  for my $arg (split(/ +/, $args)) {
    next unless $arg; 
  
    if (index($arg, "@") == -1) {
      # We're not dealing with a userhost, time to find a match
      $server->redirect_event('userhost', 1, $arg, 0, undef, {
          'event 302' => 'redir gline userhost',
          '' => 'event empty' } );
      $server->send_raw("USERHOST :$arg");
      my $uh = {
        tag   => $tag,
        nick  => lc($arg)
      };
      push @userhosts, $uh;
    } else {
      # specified mask
      my $ban;
      $ban = "*!" if (index($arg, "!") == -1);
      $ban .= $arg;
      ban_execute($tag, 0, $ban);
    }
  }
}

sub userhost_red {
  my ($server, $data) = @_;

  # Strip out our own userdata
  $data =~ s/^[^ ]* :?//;

  my $uh = shift @userhosts;
  
  if ($data && $data =~ /^([^=\*]*)\*?=.(.*)@(.*)/ && (lc($1) eq $uh->{nick})) {
    # Get the userdata we need
    my ($user, $host) = (lc($2), lc($3));

    # Set the gline
    ban_execute($uh->{tag}, 0, make_ban($user, $host));
  } else {
    # Apparently the user is no longer online
    Irssi::print("%R>>%n No such nickname: [ $uh->{nick} ]");
    $b{$uh->{tag}}--;
    return unless ($b{$uh->{tag}});
  }
}

sub ban_execute ($$$) {
  my ($tag, $nick, $ban) = @_;

  # Make sure we're glining in the right context
  my $serv = Irssi::server_find_tag($tag);
     
  # Gline the user
  $serv->command("QUOTE gline +$ban 3d :User is banned");    
  
  $b{$tag}--;
}
            
sub make_ban ($$) {
  my ($user, $host) = @_;
          
  $user =~ s/^[~+\-=^]/*/;  
  
  # Form the mask
  if ($host =~ /\d$/) {
    $host =~ s/\.[0-9]+$/.*/;
  } else {
    $host =~ s/^[^.]+\./*./ if $host =~ /^.*\..*\..*$/;
  }

  return ($user . "@" . $host);
}

Irssi::command_bind 'gl' => \&cmd_gline;
Irssi::signal_add 'redir gline userhost' => \&userhost_red;

